﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FormulParserNamespace
{
    public class PostfixParserOld
    {
        string inputString;
        List<string> element;
        SortedSet<string> variables;
        Stack<string> postfix;

        SortedSet<string> operations;

        void setOperations()
        {
            operations = new SortedSet<string>();
            operations.Add("+");
            operations.Add("-");
            operations.Add("*");
            operations.Add("/");
            operations.Add("^");
            operations.Add("sin");
            operations.Add("cos");
            operations.Add("ln");
            operations.Add("exp");
            operations.Add("(");
        }

        public PostfixParserOld() 
        {
            inputString = "";
            setOperations();
            element = parseToElement();
            variables = SetVariablesSet();
            postfix = parseToPostfix();
        }

        public PostfixParserOld(string formul)
        {
            inputString = formul;
            setOperations();
            element = parseToElement();
            variables = SetVariablesSet();
            postfix = parseToPostfix();
        }

        public List<string> GetElements()
        {            
            return element;
        }

        public SortedSet<string> GetVariables()
        {
            return variables;
        }

        public Stack<string> GetPostfix()
        {
            return postfix;
        }

        List<string> parseToElement()
        {
            List<string> res = new List<string>();
            int i = 0;
            while(i < inputString.Length)
            {
                string tmp = "";

                switch (inputString[i])
                {
                    case ' ':
                        tmp = " ";
                        break;
                    case '+':
                        tmp = "+";
                        break;
                    case '-':
                        tmp = "-";
                        break;
                    case '*':
                        tmp = "*";
                        break;
                    case '/':
                        tmp = "/";
                        break;
                    case '^':
                        tmp = "^";
                        break;
                    case '(':
                        tmp = "(";
                        break;
                    case ')':
                        tmp = ")";
                        break;
                    default:
                        break;
                }
                bool flag = false;
                while (inputString[i] == '0' || inputString[i] == '1' || inputString[i] == '2' ||
                    inputString[i] == '3' || inputString[i] == '4' || inputString[i] == '5' ||
                    inputString[i] == '6' || inputString[i] == '7' || inputString[i] == '8' ||
                    inputString[i] == '9' || inputString[i] == ',')
                {
                    flag = true;
                    tmp += inputString[i];
                    i++;
                    if (i >= inputString.Length) break;
                }
                if (tmp == "")
                {
                    while (inputString[i] != ' ' && inputString[i] != '+' && inputString[i] != '-' &&
                        inputString[i] != '*' && inputString[i] != '/' && inputString[i] != '^' &&
                        inputString[i] != '(' && inputString[i] != ')')
                    {
                        flag = true;
                        tmp += inputString[i];
                        i++;
                        if (i >= inputString.Length) break;
                    }
                }
                if (flag) i--;
                if ( tmp != " ") res.Add(tmp);
                i++;
            }
            return res;
        }

        SortedSet<string> SetVariablesSet()
        {
            SortedSet<string> res = new SortedSet<string>();
            
            foreach(string var in element)
            {
                if (var[0] != '+' && var[0] != '-' && var[0] != '*' && var[0] != '/' &&
                    var[0] != '^' && var[0] != '(' && var[0] != ')' &&
                    var[0] != '0' && var[0] != '1' && var[0] != '2' && var[0] != '3' &&
                    var[0] != '4' && var[0] != '5' && var[0] != '6' && var[0] != '7' &&
                    var[0] != '8' && var[0] != '9' && !(operations.Contains(var))) res.Add(var);
            }

            return res;
        }

        Stack<string> parseToPostfix()
        {
            Stack<string> res = new Stack<string>();
            Stack<string> tmp = new Stack<string>();

            int i = 0;
            while( i < element.Count)
            {
                if (!(operations.Contains(element[i])) && element[i] != ")") res.Push(element[i]);
                else if (operations.Contains(element[i]) && element[i] != "(")
                {
                    if (tmp.Count == 0) tmp.Push(element[i]);
                    else if (getPriority(tmp.Peek()) < getPriority(element[i])) tmp.Push(element[i]);
                    else
                    {
                        while (tmp.Count != 0)
                        {
                            res.Push(tmp.Peek());
                            tmp.Pop();
                            if(tmp.Count != 0) if (getPriority(tmp.Peek()) < getPriority(element[i])) break;
                        }
                        tmp.Push(element[i]);
                    }
                }
                else if (element[i] == "(") tmp.Push(element[i]);
                else if (element[i] == ")")
                {
                    while (tmp.Peek() != "(")
                    {
                        res.Push(tmp.Peek());
                        tmp.Pop();                        
                    }
                    tmp.Pop();
                }                   
                i++;
            }

            while (tmp.Count != 0)
            {
                res.Push(tmp.Peek());
                tmp.Pop();                
            }

            return res;
        }

        int getPriority(string c)
        {
            int res = -1;
            switch(c)
            {
                case "(":
                    res = 1; 
                    break;
                case "+":
                    res = 2;
                    break;
                case "-":
                    res = 2;
                    break;
                case "*":
                    res = 3;
                    break;
                case "/":
                    res = 3;
                    break;
                case "^":
                    res = 4;
                    break;
                case "sin":
                    res = 5;
                    break;
                case "cos":
                    res = 5;
                    break;
                case "ln":
                    res = 5;
                    break;
                case "exp":
                    res = 5;
                    break;
            }
            return res;
        }
    }
}
